﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Raven.Client;
using TodoApp.Repositories.Contract;

namespace TodoApp.Repositories
{
    public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        public IDocumentSession DocumentSession { get; set; }

        public BaseRepository(IDocumentSession session)
        {
            DocumentSession = session;
        }

        public TEntity Get(ValueType id)
        {
            return DocumentSession.Load<TEntity>(id);
        }

        public IList<TEntity> GetAll()
        {
            return DocumentSession.Query<TEntity>().ToList();
        }

        public TEntity FindOne(Expression<Func<TEntity, bool>> predicate)
        {
            return predicate == null ? DocumentSession.Query<TEntity>().FirstOrDefault() : DocumentSession.Query<TEntity>().FirstOrDefault(predicate);
        }

        public IList<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
        {
            return predicate == null ? DocumentSession.Query<TEntity>().ToList() : DocumentSession.Query<TEntity>().Where(predicate).ToList();
        }

        public IList<TEntity> Find(out int totalRecords, int pageSize, int pageIndex, Expression<Func<TEntity, bool>> predicate = null)
        {
            RavenQueryStatistics statistics;
            var query = DocumentSession.Query<TEntity>();
            IList<TEntity> documents;
            if (predicate == null)
            {
                documents = query.Statistics(out statistics).Skip(pageIndex).Take(pageSize).ToList();
                totalRecords = statistics.TotalResults;

                return documents;
            }

            documents = query.Statistics(out statistics).Where(predicate).Skip(pageIndex).Take(pageSize).ToList();
            totalRecords = statistics.TotalResults;

            return documents;
        }

        public void Add(TEntity entity)
        {
            DocumentSession.Store(entity);
        }

        public void Delete(TEntity entity)
        {
            DocumentSession.Delete(entity);
        }
    }
}